/**
 * @title HHAdminbaseAction.java
 * @description 	管理应用动作基类文件
 * @create 			2012-7-26 下午05:20:10 By xjiujiu
 * @package 		apps.admin.action
 * @copyright 		Copyright (c) 2011-2012 http://xyrj.hhtc.edu.cn.com. All right reserved
 * @version         $Id$
 * XYRJ-Java-Project
 */

package apps.admin.action;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import system.config.HHConfig;

import apps.admin.form.HHOperationForm;
import apps.admin.form.HHSearchForm;
import apps.admin.model.HHModelBaseModel;

import com.xyrj.annotation.AHHBeforeAdvice;
import com.xyrj.exception.HHActionException;
import com.xyrj.exception.HHPojoException;
import com.xyrj.exception.HHRequestException;
import com.xyrj.exception.HHUploadFileException;
import com.xyrj.exception.HHValidateException;
import com.xyrj.filesystem.HHFile;
import com.xyrj.filesystem.HHFileMimeType;
import com.xyrj.mvc.HHAction;
import com.xyrj.mvc.HHModel;
import com.xyrj.utils.HHPage;
import com.xyrj.utils.HHPojoUtils;
import com.xyrj.utils.HHString;

/**
 * Action基类
 * @ClassName: HHActionBaseAction 
 * @Description:
 * @author maoyun0903(maoyun19900818@163.com);
 * @date 2012-10-8 下午8:58:46 
 * @version V1.0
 */
@SuppressWarnings("serial")
@AHHBeforeAdvice({"this.hasLogined"})
public abstract class HHActionBaseAction extends HHAction
{

	/**
	 * 所支持的快捷操作项
	 * 
	 * @description
	 * 
	 * @classname 	OperationType 
	 * @author 		xjiujiu<xjiujiu@foxmail.com>
	 * @date 		2012-8-12 下午4:04:58 
	 * @version 	1.0
	 */
	public enum OperationType {
		 DEL, DEL_IMAGE, DEL_FILE,
		 NOT_PASS, PASSING, PASS,
		 NOT_TOP, TOP
	}

	/**
	 * @Fields static final Map<String, OperationType> 支持的操作映射表
	 */
    protected static final Map<String, OperationType> _operationMap;
	static {
		_operationMap = new HashMap<String, OperationType>(){{
			put("del", OperationType.DEL);
			put("delimage", OperationType.DEL_IMAGE);
			put("delfile", OperationType.DEL_FILE);
			put("notpass", OperationType.NOT_PASS);
			put("pass", OperationType.PASS);
			put("passing", OperationType.PASSING);
			put("top", OperationType.TOP);
			put("nottop", OperationType.NOT_TOP);
		}};
	}
	
	/** 
     * @see HHAction#HHAction(HttpServletRequest, HttpServletResponse)
     */
    public HHActionBaseAction(HttpServletRequest request,
            HttpServletResponse response)
    {
	    super(request, response);
    }

	/**
	 * 对用户是否登陆进行自动检测
	 * 
	 * @return void
	 */
	public void hasLogined()
	{
		if(false == HHIndexAction.isLogined(this._view)) {
			this._view.redirect(HHConfig.SITE_URL + "/index.jsp/admin");
		}
	}

    /**
     * 搜索动作
     *  
     * @description
     * 
     * @title  saerch
     * @return void
     */
    public void search() 
    {
    	try {
	    	HHSearchForm searchForm 	= new HHSearchForm();
	    	searchForm.validate(this._view);
	    	String keyword 		= this._view.getParameter("keyword");
	    	int perpage 		= 10;
	    	HHModelBaseModel model 	= this._initModel();
	        @SuppressWarnings("rawtypes")
            List<Map> list 		= model.getSearchList(keyword, this._getPageNumber(), perpage);
	    	Long totalRows 		= model.getTotalRows(model.getSearchWhere(keyword));
	    	String pageHtml 	= HHPage.getHtmls(
				this._getTotalPage(totalRows, perpage),
				this._view.getRequestUrl(),
				0
			);
	    	this._commonAssign();
	    	this._view.setRequestAttr("list", this._findRecordParentName(list));
	    	this._view.setRequestAttr("pageHtml", pageHtml);
	    	this._view.setRequestAttr("oprations", this._pojo.oprations);
	    	this._view.setRequestAttr("showFields", HHPojoUtils.getShowListFields(this._pojo)); 
	    	this._view.setRequestAttr("showFieldNames", HHPojoUtils.getShowListFieldNames(this._pojo)); 
	    	this._view.display("admin/list.jsp");
    	} catch(HHValidateException ex) {
    		this._view.alertAndGoBack(ex.getMessage());
    	} catch(HHPojoException ex) {
    		//TODO::log...
    		this._view.alertAndGoBack("精确查询不支持，请同管理员联系...");
    	}
    }
     
    /**
     * 用户模块主页方法
     *  
     * @description
     * 
     * @title  index
     * @return void
     */
    @SuppressWarnings("rawtypes")
    public void index()
    {
    	int perpage 		= 10;
    	HHModelBaseModel model 	= this._initModel();
        List<Map> list 		= model.getList(this._getPageNumber(), perpage);
    	Long totalRows 		= model.getTotalRows(null);
    	String pageHtml 	= HHPage.getHtmls(
			this._getTotalPage(totalRows, perpage),
			this._view.getRequestUrl(),
			0
		);
    	this._commonAssign();
    	this._view.setRequestAttr("list", this._findRecordParentName(list));
    	this._view.setRequestAttr("pageHtml", pageHtml);
    	this._view.setRequestAttr("oprations", this._pojo.oprations);
    	this._view.setRequestAttr("showFields", HHPojoUtils.getShowListFields(this._pojo)); 
    	this._view.setRequestAttr("showFieldNames", HHPojoUtils.getShowListFieldNames(this._pojo)); 
    	this._view.display("admin/list.jsp");
    }
   
    /**
     * 打到当前父类型的类型名
     *  
     * @description
     * 
     * @title  _findRecordParentName
     * @param  list 需要查找的记录集合
     * @return List<Map>
     */
    @SuppressWarnings("rawtypes")
    protected List<Map> _findRecordParentName(List<Map> list)
    {
    	if(true == this._needToFindParent(list)) {
    		HHModelBaseModel model 			= this._initParentModel();
	    	Map<Object, Object> parentMap 	= new HashMap<Object, Object>();
    		for(int i = 0; i < list.size(); i ++) {
    			@SuppressWarnings("unchecked")
                Map<String, Object> record 		= list.get(i);
    			Object parentId = record.get("parent_id");
    			if(null == parentId) {
    				record.put("parent_id", "无");
    				continue;
    			}
				if(parentMap.containsKey(parentId)) {
    				record.put("parent_id", parentMap.get(parentId));
    				continue;
				}
    			Map<?, ?> parentRecord 		= model.getRecordById(parentId);
    			if(null == parentRecord) {
    				record.put("parent_id", "无");
    			} else {
    				parentMap.put(parentId, parentRecord.get(this._pojo.parent + "_name"));
	    			record.put("parent_id", parentRecord.get(this._pojo.parent + "_name"));
    			}
    		}
    	}
    	
    	return list;
    }
   
    /**
     * 检测是否需要去查找当前的父类元素
     *  
     * @description
     * 
     * @title  _needToFindParent
     * @param  list 当前的记录结果集
     * @return boolean 检测结果
     */
    protected boolean _needToFindParent(@SuppressWarnings("rawtypes") List<Map> list)
    {
    	if(null == list || list.size() < 1 ) {
    		return false;
    	}
    	Map<String, Object> parentFieldCfg 	= this._pojo.getFieldCfg("parent_id");
    	if(null == parentFieldCfg) {
    		return false;
    	}
    	if(null == parentFieldCfg.get("isShowList")) {
    		return false;
    	}
    	if(parentFieldCfg.get("isShowList").toString().equals("Y")) {
    		return false;
    	}
    	
    	return true;
    }

    /**
     * 添加视图动作 
     *  
     * @description
     * 
     * @title  info
     * @return void
     * @throws
     */
    @SuppressWarnings("rawtypes")
    public void addview()
    {
    	this._commonAssign();
    	this._view.setRequestAttr("nextAction", "add");
    	this._view.setRequestAttr("record", new HashMap());
    }
    
    /**
     * 编辑视图
     *  
     * @description
     * 
     * @title  editview
     * @return void
     */
    @SuppressWarnings("rawtypes")
    public void editview()
    {
    	try {
	    	int recordId 		= this._getRecordId();
	    	HHModelBaseModel model 	= this._initModel();
	    	Map record 			= (Map) model.getRecordById(recordId);
	    	this._commonAssign();
	    	this._view.setRequestAttr("record", record);
	    	this._view.setRequestAttr("nextAction", "edit");
	    	this._view.setRequestAttr("title", this._pojo.modelZhName);
    	} catch(HHRequestException ex) {
    		this._view.alertAndGoBack(ex.getMessage());
    	}
    }
	
    /**
     * 快捷操作
     *  
     * @description
     * 
     * @title  operation
     * @return void
     */
    public void operation()
    {
    	try {
    		HHOperationForm operationForm 	= new HHOperationForm();
    		operationForm.validate(this._view);
    		String operation 	= this._view.getParameter("operation");
    		if(_operationMap.containsKey(operation)) {
    			switch(_operationMap.get(operation)) {
    			case DEL:
					this._deleteById(this._view.getParameterValues("record_id"));
    				break;
    			case DEL_IMAGE:
    				this._operationDelFile("image_path");
    				break;
    			case DEL_FILE:
    				this._operationDelFile("file_path");
    				break;
    			case NOT_PASS:
    				this._operationUpdate("pass_flag", "1");
    				break;
    			case PASSING:
    				this._operationUpdate("pass_flag", "2");
    				break;
    			case PASS:
    				this._operationUpdate("pass_flag", "3");
					break;
    			case NOT_TOP:
    				this._operationUpdate("top_flag", "1");
    				break;
    			case TOP:
    				this._operationUpdate("top_flag", "2");
    				break;
    			}
    			this._view.alertAndRefresh("执行操作成功！");
    		} else {
    			this._view.alertAndRefresh("操作不支持！");
    		}
    	} catch(HHValidateException ex) {
    		this._view.alertAndGoBack(ex.getMessage());
    	} catch(HHActionException ex) {
    		this._view.alertAndGoBack(ex.getMessage());
    	}
    }
   
    /**
     * 批量删除文件字段
     *  
     * @description
     * 
     * @title  _operationDelFile
     * @param  String field 字段名
     * @return void
     * @throws HHActionException 
     * @throws IOException 
     */
    protected void _operationDelFile(String field) throws HHActionException
    {
    	HHModelBaseModel model 	= this._initModel();
		String[] recordIds 	= this._view.getParameterValues("record_id");
		for(String recordId : recordIds) {
			@SuppressWarnings("rawtypes")
            Map record 		= model.getRecordById(recordId);
			if(null == record) {
				continue;
			}
		    String[] primaryKeys 	= HHPojoUtils.getPrimaryKey(this._pojo);
		    if(null == primaryKeys || primaryKeys.length < 1) {
		    	throw new HHActionException("表里没有定义主键，不能执行此操作！");
		    }
			if(1 > model.updateFieldById(field, "",
				record.get(primaryKeys[0]).toString())) {
				//Log...
				throw new HHActionException(
					"更新字段ID为" +
					record.get(primaryKeys[0]) +
					"的记录失败！操作被迫终止..."
				);
			}
			if(record.containsKey(field) && 
				!record.get(field).equals("")) {
				if(false == this._deleteFile(field, record.get(field).toString())) {
					//Log...
					throw new HHActionException("对应文件删除失败！");
				}
			}
		}
    }
    
    /**
     * 批量更新的操作 
     *  
     * @description
     * 
     * @title  _operationUpdate
     * @param  String field 需要更新的字段
     * @param  String value 更新后的值
     * @return void
     * @throws HHActionException 动作执行异常
     */
    protected void _operationUpdate(String field, String value) throws HHActionException
    {
    	HHModelBaseModel model 	= this._initModel();
		if(1 > model.updateFieldById(field, value,
			this._view.getParameterValues("record_id"))) {
			//Log...
			throw new HHActionException(
				"更新失败！操作被迫终止..."
			);
		}
    }

    /**
     * 上传图片
     *  
     * 根据用户指定的字段，去模块的POJO类里查找对应的文件上传配置，<br/>
     * 并进行对应的检测，看当前上传的文件是否满足上传的要求，如：size(大小)、<br/>
     * type(类型)等信息。
     * 
     * @title  _uploadImage
     * @param  String field 上传文件的字段名
     * @return void
     * @throws HHUploadFileException 上传文件异常信息
     */
    @SuppressWarnings("null")
    protected void _uploadFile(String field) throws HHUploadFileException 
    {
    	Map<String, Object> fileInfo 	= this._view.getFileInfo(field);
    	if(null == fileInfo) {
    		return ;
    	}
    	HashMap<String, Object> fieldCfg 	= this._pojo.getFieldCfg(field);
    	if(null == fieldCfg && null == fieldCfg.get("type")) {
    		throw new HHUploadFileException("不允许上传文件！");
    	}
    	Double size 	= (Double)fieldCfg.get("size");
    	if(HHFile.mbToByte(size) < HHString.strToDouble((String)fileInfo.get("size"))) {
			throw new HHUploadFileException("文件太大, 请参考说明信息~");
    	}
    	if(false == HHFileMimeType.isMimeType(
			(String[])fieldCfg.get("type"),
			fileInfo.get("type").toString()
		)) {
    		HHFile.deleteFile((String)fileInfo.get("path"));
    		throw new HHUploadFileException("文件格式不支持，请参考说明信息~");
    	}
    	try {
    		String saveFilePath 	= this._genSaveFilePath((String)fileInfo.get("name"));
	    	if(true == HHFile.moveFile(
				(String)fileInfo.get("path"),
				HHConfig.ROOT_PATH + "/" + saveFilePath,
				true)) {
	    		this._pojo.setField(field, saveFilePath);
	    		return;
	    	}
    	} catch (FileNotFoundException ex) {
    		if(HHConfig.DEBUG) {
    			System.out.println(ex.getMessage());
    		}
    	} catch(IOException ex) {
    		if(HHConfig.DEBUG) {
    			System.out.println(ex.getMessage());
    		}
    	} finally {
			HHFile.deleteFile((String)fileInfo.get("path"));
    	}
		throw new HHUploadFileException("上传文件失败！请联系管理员～");
	}
   
    /**
     * 生成文件存储路径
     *  
     * @description
     * 
     * @title  _genSaveFilePath
     * @param  String fileName 当前的文件名
     * @return String 生成的目标路径
     */
    protected String _genSaveFilePath(String fileName)
    {
    	return HHConfig.RESOURCE_PATH +
		    	"/images/" +
		    	fileName;
    }
   
    /**
     * 删除旧文件
     *  
     * @description
     * 
     * @title  _deleteOldFile
     * @param  String field 当前的字段
     * @return boolean 是否删除成功
     */
    protected boolean _deleteOldFile(String field)
    {
    	String oldFilePath 	= (String)this._view.getParameter("old_" + field);
    	if(null == oldFilePath || oldFilePath.equals("")) {
    		return true;
    	}
    	
    	return _deleteFile(field, oldFilePath);
    }

	/** 
     * 删除记录文件及相关的文件 
     * 
     * @description
     * 
     * @title  _deleteFile
     * @param  String field 发前的字段名
     * @param  String filePath 需要删除的文件路径
     * @return boolean 是否删除成功 
     */
    protected boolean _deleteFile(String field, String filePath)
    {
	    if(null == this._pojo.getField(field) ||
			this._pojo.getField(field).equals("")) {
    		return true;
    	}
    	Map<String, Object> fieldCfg 	= this._pojo.getFieldCfg(field);
		if(null != fieldCfg.get("zoom")) {
			int[] zoom 	= (int[])fieldCfg.get("zoom");
			String fileParentDir 	= HHFile.getParentDir(filePath);
			String baseName 		= HHFile.getBaseName(filePath);
			String extension 		= HHFile.getExtension(filePath);
			for(int i = 0; i < zoom.length; i+= 2) {
				String zoomFilePath = HHConfig.ROOT_PATH + "/" +
									  fileParentDir + "/" +
									  baseName + zoom[i] + "-" + zoom[i+1] +
									  extension;
				if(false == HHFile.deleteFile(zoomFilePath)) {
					return false;
				}
			}
		}
		
		return HHFile.deleteFile(HHConfig.ROOT_PATH + "/" + filePath);
    }

    /**
     * 赋值模块的Pojo对象
     *  
     * @description
     * 
     * @title  _assginPojo
     * @return void
     */
    @SuppressWarnings("rawtypes")
    protected void _assginPojoByAdd()
    {
    	Iterator fields 	= this._pojo.getFields();
    	while(fields.hasNext()) {
    		String field  	= (String)(fields.next());
    		if(false == this._pojo.isFileField(field) &&
    		   null != this._view.getParameter(field) &&
    		   !this._view.getParameter(field).equals("")) {
    			this._pojo.setField(field, this._view.getParameter(field));
    		}
    	}
    }
    
    /**
     * 按照编辑的要求给POJO赋值
     *  
     * @description
     * 
     * @title  _assginPojoByEdit
     * @return void
     */
    @SuppressWarnings("rawtypes")
    protected void _assginPojoByEdit()
    {
    	Iterator fields 		= this._pojo.getFields();
    	while(fields.hasNext()) {
    		String field  	= (String)(fields.next());
    		if(false == this._pojo.isFileField(field) &&
    		   null != this._view.getParameter(field)) {
    		   this._pojo.setField(field, this._view.getParameter(field));
    		}
    	}
    }
   
    /**
     * 删除记录
     *  
     * @description
     * 
     * @title  delete
     * @return void
     */
    public void delete()
    {
    	try {
    		this._deleteById(this._getRecordId());
    		this._view.alertAndRefresh("删除成功！");
    	} catch(HHRequestException ex) {
    		this._view.alertAndGoBack(ex.getMessage());
    	} catch(HHActionException ex) {
    		this._view.alertAndGoBack(ex.getMessage());
    	}
    }
   
    /**
     * 通过记录ID来删除对应的记录 
     *  
     * @description
     * 
     * @title  _delete
     * @param  Object recordIds 当前的记录ID
     * @throws HHActionException 执行动作过程中的异常
     * @return void
     */
    protected void _deleteById(Object ids) throws HHActionException
    {
		HHModelBaseModel  model = this._initModel();
		String [] recordIds = null;
		if(!(ids instanceof String[])) {
			recordIds 		= new String[] {ids.toString()};
		} else {
			recordIds 		= (String [])ids;
		}
		for(String recordId : recordIds) {
			@SuppressWarnings("rawtypes")
            Map record 			= model.getRecordById(recordId);
			if(null == record) {
				throw new HHActionException("记录不存在！");
			}
			if(0 < model.delete(recordId)) {
				if(null != record.get("image_path") && 
					false == this._deleteFile("image_path",
					HHConfig.ROOT_PATH + "/" + record.get("image_path").toString())) {
					//log..
					throw new HHActionException("删除记录相关图片失败！");
				}
				continue;
			}
			throw new HHActionException("删除失败！请同管理员联系～");
		}
    }
   
    /**
     * 公共的赋值到Request对象方法
     *  
     * @description
     * 
     * @title  _commonAssign
     * @return void
     */
    protected void _commonAssign()
    {
    	this._view.setRequestAttr("modelEnName", this._pojo.modelEnName);
    	this._view.setRequestAttr("modelZhName", this._pojo.modelZhName);
    }
   
    /**
     * 得到当前模块的父类记录 
     *  
     * @description
     * 
     * @title  getParentList
     * @param  HHModel typeModel 当前模块所属类型的数据库操作对象
     * @return void
     */
    protected void _assignParentList(HHModel typeModel)
    {
    	@SuppressWarnings("rawtypes")
        List<Map> parentList 		= typeModel.getAllRecords();
    	this._view.setRequestAttr("parentList", parentList);
    	this._view.setRequestAttr("parent", this._pojo.parent);
    }
    
    /**
     * 返回当前的模块数据库操作对象
     *  
     * @description
     * 
     * @title  initModel
     * @return HHModelBaseModel 模块数据库操对象
     */
    protected abstract HHModelBaseModel _initModel();
   
    /**
     * 初始化当前模块的父类模块
     *  
     * @description
     * 
     * @title  _initParentModel
     * @return HHModelBaseModel 父类模块实例
     */
    protected abstract HHModelBaseModel _initParentModel();
    
}
